package com.yizisu.basemvvm.mvvm

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response

import java.lang.reflect.ParameterizedType

/**
 * 若红楼梦空，亦初心不变
 * 作者：kotle
 * 包名：com.yizisu.basemvvm.mvvm
 * 时间：2019/1/17 23:10
 * 描述：
 */
abstract class MvvmViewModel : ViewModel() {

    /**
     * 存储Model
     */
    val modelList = mutableListOf<MvvmModel>()

    /**
     * 创建Model
     */
    inline fun <reified T : MvvmModel> getModel(): T {
        for (mvvmModel in modelList) {
            if (mvvmModel is T) {
                return mvvmModel
            }
        }
        val instance = T::class.java.newInstance()
        modelList.add(instance)
        return instance
    }


    /**
     * 做一写清理操作
     */
    override fun onCleared() {
        callList.forEach {
            if (!it.isCanceled) {
                it.cancel()
            }
        }
        callListRetrofit.forEach {
            if (!it.isCanceled) {
                it.cancel()
            }
        }
        modelList.forEach {
            it.onCleared()
        }
        modelList.clear()
        super.onCleared()
    }


    private val callList = mutableListOf<Call>()

    /**
     * 销毁的时候结束请求
     */
    fun Call.cancelOnDestroy(): Call {
        callList.add(this)
        return this
    }

    /**
     * 异步执行
     * 销毁的时候结束请求
     */
    fun Call.async(callback: Callback) {
        callList.add(this)
        enqueue(callback)
    }

    /**
     * 同步执行
     * 销毁的时候结束请求
     */
    fun Call.await(): Response {
        callList.add(this)
        return execute()
    }

    /**
     * retrofit
     */
    private val callListRetrofit = mutableListOf<retrofit2.Call<*>>()


    fun <BO> retrofit2.Call<BO>.cancelOnDestroy(): retrofit2.Call<BO> {
        callListRetrofit.add(this)
        return this
    }

    fun <BO> retrofit2.Call<BO>.async(callback: retrofit2.Callback<BO>) {
        callListRetrofit.add(this)
        enqueue(callback)
    }

    fun <BO> retrofit2.Call<BO>.await(): retrofit2.Response<BO> {
        callListRetrofit.add(this)
        return execute()
    }
}